﻿using System.Text.RegularExpressions;
using System.Web.Http.Description;
using Swashbuckle.Swagger;

namespace HuntingFishGame.CustomerApi.App_Start.Swagger
{
    /// <summary>
    /// 格式化注释，支持在注释中使用Markdown语法
    /// </summary>
    public class FormatXmlCommentProperties : IOperationFilter
    {
        //支持类型如下Markdown格式的注释

        /// <summary>
        /// Gets a the list of entities and their descriptions from the Entity Service.
        /// </summary>
        /// <remarks>
        /// ### REMARKS ###
        /// Use this call to retrieve a list of entities and their descriptions. This is used when setting up a new ViewSet.
        /// - Returns an array of **EntityDescription** objects.
        /// - The array is `ordered alphabetically` by the Name property.
        /// <!-- 
        /// <code>
        ///     // contrived code sample to demonstrate code block in swagger.
        ///     for (i=0; i < 5; i++)
        ///     {
        ///         doesthiswork = yesitdoes;
        ///     }
        /// </code>
        /// -->
        /// </remarks>
        /// <response code="200">OK</response>
        /// <returns>An array of EntityDescription objects.</returns>
        
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            operation.description = Formatted(operation.description);
            operation.summary = Formatted(operation.summary);
        }


        private string Formatted(string text)
        {
            if (text == null) return null;

            // Strip out the whitespace that messes up the markdown in the xml comments,
            // but don't touch the whitespace in <code> blocks. Those get fixed below.
            string resultString = Regex.Replace(text, @"(^[ \t]+)(?![^<]*>|[^>]*<\/)", "", RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"<code[^>]*>", "<pre>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"</code[^>]*>", "</pre>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"<!--", "", RegexOptions.Multiline);
            resultString = Regex.Replace(resultString, @"-->", "", RegexOptions.Multiline);

            try
            {
                string pattern = @"<pre\b[^>]*>(.*?)</pre>";

                foreach (Match match in Regex.Matches(resultString, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline))
                {
                    var formattedPreBlock = FormatPreBlock(match.Value);
                    resultString = resultString.Replace(match.Value, formattedPreBlock);
                }
                return resultString;
            }
            catch
            {
                // Something went wrong so just return the original resultString
                return resultString;
            }
        }

        private string FormatPreBlock(string preBlock)
        {
            // Split the <pre> block into multiple lines
            var linesArray = preBlock.Split('\n');
            if (linesArray.Length < 2)
            {
                return preBlock;
            }
            else
            {
                // Get the 1st line after the <pre>
                string line = linesArray[1];
                int lineLength = line.Length;
                string formattedLine = line.TrimStart(' ', '\t');
                int paddingLength = lineLength - formattedLine.Length;

                // Remove the padding from all of the lines in the <pre> block
                for (int i = 1; i < linesArray.Length - 1; i++)
                {
                    linesArray[i] = linesArray[i].Substring(paddingLength);
                }

                var formattedPreBlock = string.Join("", linesArray);
                return formattedPreBlock;
            }

        }
    }
}